package org.example.events.hostable.harassment;

import org.example.item.ball.Ball;
import org.example.models.abstracts.AbstractEvent;
import org.example.models.abstracts.AbstractLiving;
import org.example.models.interfaces.own.Ownable;
import org.example.nonmaterial.Relationship;
import org.example.person.Person;

import java.util.*;

public class HarassmentEvent extends AbstractEvent implements Ownable {

    private enum Message {
        ENTERED_AS_PARTICIPANT("присоединиться в качестве участника"),
        ENTERED_AS_WATCHER("присоединиться в качестве зрителя"),
        THROW("кидать мяч"),
        ENJOY("веселиться"),
        RAGE("злиться"),
        PAIN("испытывать боль");
        private final String message;
        Message(String message) { this.message = message; }

        @Override
        public String toString() {
            return message;
        }
    }

    protected record Participant(Person person, List<Ball> items) {}

    private final Queue<Participant> participants;

    private AbstractLiving victim;

    public HarassmentEvent() {
        super("HarassmentEvent");
        participants = new LinkedList<>();
    }

    protected void setVictim(AbstractLiving victim) {
        removeObserver(this.victim);
        this.victim = victim;
        addObserver(victim);
    }

    protected boolean processParticipant() {
        Participant participant = participants.poll();
        if(participant == null) return false;

        Person person = participant.person();
        List<Ball> personItems = participant.items();
        List<Ball> itemsToThrow = participant.items();


        for(int i = 0; i < itemsToThrow.size(); i++) {
            notifyObserver(person, Message.THROW);
            notifyObserver(victim, Message.PAIN);
        }
        personItems.removeAll(itemsToThrow);

        observers.stream()
                .filter(observer -> !observer.equals(victim))
                .forEach(observer -> {
                    List<Ownable> observerOwnables = ((Person) observer).getOwnables();
                    boolean isFriend = observerOwnables.stream()
                            .filter(Relationship.class::isInstance)
                            .map(Relationship.class::cast)
                            .anyMatch(relationship -> relationship.personA.equals(victim) || relationship.personB.equals(victim));

                    if(isFriend) {
                        notifyObserver(observer, Message.RAGE);
                    } else {
                        notifyObserver(observer, Message.ENJOY);
                    }
        });


        return true;
    }



    protected void addParticipant(Participant participant) {
        addObserver(participant.person());
        notifyObserver(participant.person(), Message.ENTERED_AS_PARTICIPANT);
        participants.add(participant);
    }

    protected void addWatcher(Person person) {
        addObserver(person);
        notifyObserver(person, Message.ENTERED_AS_WATCHER);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof HarassmentEvent that)) return false;
        return Objects.equals(victim, that.victim);
    }

    @Override
    public int hashCode() {
        return Objects.hash(victim);
    }

    @Override
    public String toString() {
        return "HarassmentEvent[victim=" + victim + "]";
    }
}
